home *** CD-ROM | disk | FTP | other *** search
/ Whiteline: delta / whiteline CD Series - delta.iso / systems / unixtkit / wc / wc.c < prev    next >
C/C++ Source or Header  |  1995-11-25  |  5KB  |  266 lines

  1. /****************************************************************/
  2. /*    Count the characters, words and lines in a file.    */
  3. /*                                */
  4. /*    By David Megginson, 1991                */
  5. /*    Released into the public domain.            */
  6. /*                                */
  7. /*    Command line options:                    */
  8. /*        -c    Count characters            */
  9. /*        -w    Count words                */
  10. /*        -l    Count lines                */
  11. /*    (count everything by default)                */
  12. /*                                */
  13. /*    Makefile options:                    */
  14. /*        -DBUFFER_SIZE=n        Read n bytes at a time    */
  15. /*        -DSKIP_CR        Ignore carriage returns    */
  16. /****************************************************************/
  17.  
  18.  
  19. /* $Id: wc.c,v 1.2 1991/03/05 09:02:30 david Exp david $ */
  20.  
  21. /*
  22.  * $Log: wc.c,v $
  23.  * Revision 1.2  1991/03/05  09:02:30  david
  24.  * Changed `static version' to `static char * version' (duh!)
  25.  *
  26.  * Revision 1.1  1991/03/05  08:59:46  david
  27.  * Initial revision
  28.  *
  29.  */
  30.  
  31. static char * version = "$Id: wc.c,v 1.2 1991/03/05 09:02:30 david Exp david $";
  32.  
  33.  
  34. #include <stdio.h>
  35. #include <stddef.h>
  36. #include <stdlib.h>
  37. #include <unistd.h>
  38. #include <fcntl.h>
  39. #include <errno.h>
  40.  
  41. /* The string of legal options for getopt            */
  42.  
  43. #define    OPTSTRING    "clw"
  44.  
  45. /* The size of the read() buffer. Allow the user to define    */
  46. /* this in the Makefile if desired.                */
  47.  
  48. #ifndef    BUFFER_SIZE
  49. #define    BUFFER_SIZE    50000L
  50. #endif
  51.  
  52. /* Use this buffer to read in the file                */
  53.  
  54. static char buffer[BUFFER_SIZE];
  55.  
  56. /* Number of files read so far, and running totals        */
  57.  
  58. static int total_files = 0;
  59. static long total_characters = 0;
  60. static long total_words = 0;
  61. static long total_lines = 0;
  62.  
  63. /* Flags controlled by command-line options            */
  64.  
  65. static int all_flag = 1;    /* count everything (default)    */
  66. static int c_flag = 0;        /* count characters        */
  67. static int w_flag = 0;        /* count words            */
  68. static int l_flag = 0;        /* count lines            */
  69. static int whitespace_flag = 1;    /* whitespace seen        */
  70. static int nl_flag = 0;        /* newline seen            */
  71.  
  72. /* getopt() stuff                        */
  73.  
  74. extern int optind;
  75.  
  76. /* Local functions                    */
  77.  
  78. static void do_file( const char * filename,int fd );
  79. static void count_buffer( long * c,long * w,long * l,fpos_t length );
  80. static void show_results( long c,long w,long l,const char * filename );
  81. static void show_totals( void );
  82.  
  83.  
  84. main( int ac,const char ** av )
  85. {
  86.     int opt,current,fd;
  87.  
  88.     opt = getopt(ac,av,OPTSTRING);
  89.     while( opt != EOF ) {
  90.         switch( opt ) {
  91.  
  92.         case 'c':
  93.             all_flag = 0;
  94.             c_flag = 1;
  95.             break;
  96.         case 'l':
  97.             all_flag = 0;
  98.             l_flag = 1;
  99.             break;
  100.         case 'w':
  101.             all_flag = 0;
  102.             w_flag = 1;
  103.             break;
  104.         }
  105.         opt = getopt(ac,av,OPTSTRING);
  106.     }
  107.  
  108.     if( optind == ac ) {
  109.         do_file(NULL,0);
  110.     } else for( current = optind; current < ac; current++ ) {
  111.         if( !strcmp(av[current],"-") )
  112.             do_file(av[current],0);
  113.         else {
  114.             fd = open(av[current],O_RDONLY);
  115.             if( fd < 0 ) {
  116.                 perror(av[current]);
  117.                 exit(1);
  118.             }
  119.             do_file(av[current],fd);
  120.             close(fd);
  121.         }
  122.     }
  123.  
  124.     if( total_files > 1 )
  125.         show_totals();
  126.     return 0;
  127. }
  128.  
  129.     
  130. /*******
  131.     Count the words in a single file.
  132.  
  133.     Arguments:    const char * filename    the file name
  134.             int fd            the file descriptor
  135.     Return value:    none
  136. *******/
  137.  
  138. static void
  139. do_file( const char * filename,int fd )
  140. {
  141.     fpos_t total_read;
  142.     long c=0, w=0, l=0;
  143.  
  144.     whitespace_flag = 1;
  145.     total_files++;
  146.     
  147.     do {
  148.         total_read = read(fd,buffer,BUFFER_SIZE);
  149. #if DEBUG
  150. printf("Read %ld characters from %s\n",total_read,filename?filename:"stdin");
  151. #endif
  152.         if( total_read > 0 )
  153.             count_buffer(&c,&w,&l,total_read);
  154.     } while( total_read == BUFFER_SIZE );
  155.  
  156.     /* if the file ended on a word, count that word too    */
  157.     
  158.     if( !whitespace_flag )
  159.         w++;
  160.  
  161.     /* if the last character was not NL, count the last    */
  162.     /* line                            */
  163.  
  164.     if( !nl_flag )
  165.         l++;
  166.         
  167.     show_results(c,w,l,filename);
  168.  
  169.     total_characters += c;
  170.     total_words += w;
  171.     total_lines += l;
  172. }
  173.  
  174.  
  175. /*******
  176.     Count the buffer itself.
  177.  
  178.     Arguments:    long * c    characters
  179.             long * w    words
  180.             long * l    lines
  181.             fpos_t length    characters in buffer
  182.     Return value:    none
  183. *******/
  184.  
  185. void
  186. count_buffer( long * c,long * w,long * l,fpos_t length )
  187. {
  188.     fpos_t pos;
  189.  
  190.     for( pos = 0; pos < length; pos++ ) {
  191.  
  192.         switch( buffer[pos] ) {
  193. #ifdef SKIP_CR
  194.         case '\r':
  195.             break;
  196. #endif
  197.         case '\n':
  198.             (*l)++;
  199.             if( !whitespace_flag )
  200.                 (*w)++;
  201.             whitespace_flag = 1;
  202.             nl_flag = 1;
  203.             break;
  204.         case ' ':
  205.         case '\t':
  206.             if( !whitespace_flag )
  207.                 (*w)++;
  208.             whitespace_flag = 1;
  209.             break;
  210.         default:
  211.             whitespace_flag = 0;
  212.             break;
  213.         }
  214.  
  215.         /* Always count a character        */
  216.  
  217.         (*c)++;
  218.     }
  219. }
  220.             
  221.         
  222. /*******
  223.     Show the results for a file.
  224.  
  225.     Arguments:    long c        characters
  226.             long w        words
  227.             long l        lines
  228.             const char * filename
  229.     Return value:    none
  230. *******/
  231.  
  232. void
  233. show_results( long c,long w,long l,const char * filename )
  234. {
  235.     if( all_flag || l_flag )
  236.         printf("%10ld",l);
  237.     if( all_flag || w_flag )
  238.         printf("%10ld",w);
  239.     if( all_flag || c_flag )
  240.         printf("%10ld",c);
  241.     if( filename )
  242.         printf(" %s",filename);
  243.     printf("\n");
  244. }
  245.  
  246. /*******
  247.     Show the final total for more than one file.
  248.  
  249.     Arguments:    none
  250.     Return value:    none
  251. *******/
  252.  
  253. void
  254. show_totals()
  255. {
  256.     if( all_flag || l_flag )
  257.         printf("%10ld",total_lines);
  258.     if( all_flag || w_flag )
  259.         printf("%10ld",total_words);
  260.     if( all_flag || c_flag )
  261.         printf("%10ld",total_characters);
  262.     printf(" TOTAL\n");
  263. }
  264.  
  265.  
  266.